/**
 *    ------------ ipha function 一些函数  ------
 */
 namespace iFunction {
    /**
     * 改变节点父节点，显示位置不变
     * @param node 需要操作节点
     * @param targetParent 目标父节点
     */
    export function changeParentPosConstant(node: cc.Node, targetParent: cc.Node) {
        let startPos = node.convertToWorldSpaceAR(cc.v2(0, 0));
        let trminalPos = targetParent.convertToNodeSpaceAR(startPos);
        node.setParent(targetParent);
        node.setPosition(trminalPos);
    }

    /**
     * 创建一份json文件并下载到本地，
     * @param textToWrite 变量JSON.toJsonString后的结果
     * @param fileNameToSaveAs 设置文件名
     */
    export function saveForBrowser(textToWrite: string, fileNameToSaveAs: string = "NewJson") {
        if (cc.sys.isBrowser) {
            let textFileAsBlob = new Blob([textToWrite], { type: 'application/json' });
            let downloadLink = document.createElement("a");
            downloadLink.download = fileNameToSaveAs;
            downloadLink.innerHTML = "Download File";
            if (window.webkitURL != null) {
                downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
            }
            else {
                downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
                downloadLink.style.display = "none";
                document.body.appendChild(downloadLink);
            }
            downloadLink.click();
            downloadLink.remove();
        }
    }

    /**
     * 物体大小近似判断
     * @param fuzzyValue 大小近似比值
     * @param rect 物体大小列表
     * @returns 物体大小是否近似比值
     */
    export function sizeAreaFuzzyEquals(fuzzyValue: number, ...rect: cc.Rect[]) {
        let area01 = (rect[0].height * rect[0].width);
        let area02 = (rect[1].height * rect[1].width);
        let ratio = Math.min(area01, area02) / Math.max(area01, area02);
        return ratio >= fuzzyValue / 100;
    }

    /**
     * 比较两个对象
     * @param obj1 对象1
     * @param obj2 对象2
     * @returns 是否相等
     */
    export function isDeepObjectEqual(obj1, obj2) {

        //1.如果是比较对象===，返回true
        if (obj1 === obj2) return true;

        //2.如果比较的是两个方法，转成字符串比较
        if (typeof obj1 === "function" && typeof obj2 === "function") return obj1.toString() === obj2.toString();

        //3如果obj1和obj2都是Date实例，获取毫秒值比较
        if (obj1 instanceof Date && obj2 instanceof Date) return obj1.getTime() === obj2.getTime();

        //4如果比较是两个类型不一致,无须比较直接返回false
        if (Object.prototype.toString.call(obj1) !== Object.prototype.toString.call(obj2) || typeof obj1 !== "object") return false;

        //5.获取对象所有自身属性的属性名（包括不可枚举属性但不包括Symbol值作为名称的属性
        const obj1Props = Object.getOwnPropertyNames(obj1);
        const obj2Props = Object.getOwnPropertyNames(obj2);

        //自身属性长度相等,
        if (obj1Props.length !== obj2Props.length) return false;

        //递归调用判断每一个属性值是否相等
        return (obj1Props.every(prop => isDeepObjectEqual(obj1[prop], obj2[prop])));
    }

    /**
     * 判断数字在区间
     * @param root 需要判断的数字
     * @param min 最小值
     * @param max 最大值
     * @returns 包含最大、最小
     */
    export function numberInTheArea(root: number, min: number, max: number) {
        return root >= min && root <= max;
    }

    /**
     * 角度转弧度
     * @param angle 角度
     * @returns 弧度
     */
    export function angleToRadian(angle: number) {
        return angle * (Math.PI / 180);
    }

    /**
     * 弧度转角度
     * @param radian 弧度
     * @returns 角度
     */
    export function radianToAngle(radian: number) {
        return radian * (180 / Math.PI);
    }

    /**
     * 角度<正负>规范化
     * @param angle 需要转换的角度
     * @returns 规范后的角度
     */
    export function anglePlusOrMinus(angle: number) {
        let a = iFunction.angleTo360(angle);
        if (a > 180) {
            a -= 360;
        }
        return a;
    }

    /**
     * 角度<360度>规范化
     * @param angle 需要转换的角度
     * @returns 规范后的角度
     */
    export function angleTo360(angle: number) { 
        let a = angle % 360;
        if (a < 0) {
            a += 360;
        }
        return a;
    }

    /**
     * 他人对自己在碰撞点上的相对速度
     * @param contact 
     * @param selfCollider 
     * @param otherCollider 
     * @returns 
     */
    export function otherToSelfRelativeVelocity(contact: cc.PhysicsContact, selfCollider: cc.PhysicsBoxCollider, otherCollider: cc.PhysicsCollider) {
        const worldManifold = contact.getWorldManifold();
        let slefLV: cc.Vec2 = new cc.Vec2();
        selfCollider.body.getLinearVelocityFromWorldPoint(worldManifold.points[0], slefLV);
        let otherLV: cc.Vec2 = new cc.Vec2();
        otherCollider.body.getLinearVelocityFromWorldPoint(worldManifold.points[0], otherLV);

        return otherLV.sub(slefLV);
    }

    /**
     * 节点是否在屏幕内（未考虑节点旋转）
     * @param camara 摄像机
     * @param node 节点
     * @returns bool值
     */
    export function NodeInScreen(camara: cc.Camera, node: cc.Node) {
        const cameraWPos = camara.node.convertToWorldSpaceAR(cc.v2());
        let screen = cc.rect(cameraWPos.x, cameraWPos.y, cc.winSize.width / camara.zoomRatio, cc.winSize.height / camara.zoomRatio);
        const ndWPos = node.convertToWorldSpaceAR(cc.v2());
        let ndRect: cc.Rect = cc.rect(ndWPos.x, ndWPos.y, node.width * node.scaleX, node.height * node.scaleY);

        return ndRect.x <= screen.x + (screen.width + ndRect.width) / 2
            && ndRect.x >= screen.x - (screen.width + ndRect.width) / 2
            && ndRect.y <= screen.y + (screen.height + ndRect.height) / 2
            && ndRect.y >= screen.y - (screen.height + ndRect.height) / 2;
    }
}

export default iFunction;